<?
/**
 * $Id: Controller.mod.php 394 2008-05-28 19:28:03Z dakl $
 * Klasa kontrolera v 1.2.0
 *
 */
abstract class Controller {
	
	/**
	 * Pola w rejestrze informujace o tym czy wywołano metody opsiowe do descripion, title, etc.
	 * 
	 * @var unknown_type
	 */
	const DESCRIPTION_SET = '__description_set__';
	const TITLE_SET = '++title+set++';
	const KEYWORDS_SET = '!!keywords!set!!';

	/**
	 * Szablon dla metody
	 *
	 * @var unknown_type
	 */
	public $partialTemplate;
	/**
	 * Sciezka szablonu dla metody
	 *
	 * @var unknown_type
	 */
	public $templatePath;
	/**
	 * Wygenerowana przez metode tresc
	 *
	 * @var unknown_type
	 */
	public $content;
	/**
	 * Czas cache dla metody
	 *
	 * @var unknown_type
	 */
	public $cacheTime;

	/**
	 * Obiekt Smarty
	 *
	 * @var TemplateMaster
	 */
	protected $smarty;

	/**
	 * Obiekt request
	 *
	 * @Request
	 */
	protected $request;

	public $utf8;

	/**
	 * Zawiera url na ktory ma byc przekierowany user
	 *
	 * @var string
	 */
	private $redirect = array('url'=>'', 'time'=>'');
	/**
	 * Wylacza obsluge smarty
	 *
	 * @var unknown_type
	 */
	public $disableTemplates = false;

	public $actionRedirect = false;

	private $breadCrumbs = array();

	private $actionSet = array();

	/**
	 * pole które mówi jak będzie renderowana aktualna akcja - przydatne gdy ustawia się rendering w routach
	 * @var unknown_type
	 */
	public $renderer = 'normal';

	/**
	 * pole od danych odnośnie tabel
	 */
	public $tableParams;

	/**
	 * pole odnośnie konfigów tabel dla kontrolera
	 */
	public $tableConfig;

	/**
	 * Konstruktor klasy
	 *
	 */
	public final function __construct() {

	}
	/**
	 * Ustawia przekierowanie
	 *
	 * @param string $action (true/false/string: action)
	 *
	 */
	public final function SetActionRedirect($action) {
		$this->actionRedirect = $action;
	}
	/**
	 * Zwraca przekierowanie
	 *
	 */
	public final function GetActionRedirect() {
		return $this->actionRedirect;
	}

	public final function SetBreadCrumbs($array) {
		$this->breadCrumbs = $array;
	}

	public function SetUtf8() {
		$this->utf8 = true;
	}

	public final function GetBreadCrumbs() {
		return $this->breadCrumbs;
	}

	public final function AddBreadCrumb($title, $url = null) {
		$this->breadCrumbs[] = array('title'=>$title, 'url'=>$url);
	}

	public final function AddHeader($name, $value, $overWrite = false) {
		//TODO : New Feature - testme

		Utils::AddHeader($name, $value, $overWrite);
	}

	/**
	 * Dodawanie opisu
	 *
	 * @param unknown_type $desc
	 */
	public final function AddDescription($desc = null, $overwrite = false) {
		$true = 1;
		!Registry::Exists(self::DESCRIPTION_SET)?Registry::Set(self::DESCRIPTION_SET,$true):null;
		
		if(!is_null($desc) && $desc != "")
			Utils::AddHeader('meta', array('name'=>'description', 'content'=>$desc), $overwrite);
	}

	/**
	 * Dodawanie opisu
	 *
	 * @param unknown_type $desc
	 */
	public final function AddKeywords($keywords = null, $overwrite = false) {
		$true = 1;
		!Registry::Exists(self::KEYWORDS_SET)?Registry::Set(self::KEYWORDS_SET,$true):null;
		if(!is_null($keywords) && $keywords != "")
			Utils::AddHeader('meta', array('name'=>'keywords', 'content'=>$keywords), $overwrite);
	}
	
	public final function AddStyle($style_file, $overwrite = false) {
		Utils::AddHeader('link', array('rel' => 'stylesheet', 'type' => 'text/css', 'href' => $style_file), $overwrite);
	}

	/**
	 * Metoda przypisujaca obiekt smarty
	 *
	 * @param Smarty $smarty
	 */
	public final function SetSmarty(Smarty $smarty) {
		$this->smarty = $smarty;
	}

	/**
	 * Dodawanie elementu tytulu
	 *
	 * @param unknown_type $title
	 */
	public final function AddTitle($title, $overwrite = false) {
		$true = 1;
		!Registry::Exists(self::TITLE_SET)?Registry::Set(self::TITLE_SET,$true):null;
		
		Utils::AddHeader('title', $title, $overwrite);
	}

	/**
	 * Weryfikacja cache metody
	 *
	 * @param unknown_type $method
	 * @param unknown_type $param
	 * @return unknown
	 */
	public final function Init($method, $param = null) {

		$this->SetReturnPath(array());

		//logika werifikacji cache dla metod.
		$cacheTimeTmp = CacheParam::Get(get_class($this).$method);
		$cacheTimeTmp2 = CacheParam::Get(get_class($this));
		if(isset($cacheTimeTmp) && $cacheTimeTmp != '') {
			$cacheTime = $cacheTimeTmp;

		} else if(isset($cacheTimeTmp2) && $cacheTimeTmp2 != '') {
			$cacheTime = $cacheTimeTmp2;
		} else {
			$cacheTime = CacheParam::Get('global');

		}
		if($this->CheckLiveMethod($method)) {
			$this->cacheTime = 0;
			$this->smarty->cache_lifetime = 0;
		} else {
			$this->cacheTime = $cacheTime;
		}

		if(Core::GetAppSafeMode()) {
			return true;
		}


		    return false;


	}

	/**
	 * Czysci bufor strony
	 *
	 * @param string $method
	 * @param array $param
	 */
	public final function ClearCache($method, $param = null) {
		$cacheParam = implode('-', $param);
		$this->smarty->clear_cache($this->partialTemplate, $method.substr($cacheParam,0, 100));
	}
	
	
	
	protected function addXmlDataSet($objArrayName,$dataUrl = null,$path = null,$additionalOption = array())
	{
	    
    	    $script = "var ds$objArrayName = new Spry.Data.XMLDataSet(\"$dataUrl\",\"$path\");";
	    $this->AddScript($script, 'script');
	    
	    foreach($additionalOption as $key => $value)
	    {
		$this->AddScript("var ds$key= new Spry.Data.NestedXMLDataSet(ds$objArrayName,\"$value\"); ", 'script');
	    }

	}

	/**
	 * Dodaje skrypt do naglowka strony
	 *
	 * @param string $script
	 * @param string $type (file/code)
	 * @param string $position (top/bottom)
	 * @param int    $sort
	 */
	public final function AddScript($script, $type='file', $position='top', $sort=null) {

		if($position == 'top') {
			$name = 'javascript';
		} else {
			$name = 'footerJavascript';
		}

		$t = Registry::Get($name);
		$temp = Registry::Get($name.'_temp');
		
		if(!is_null($sort) && isset($t[$sort])) {
			throw new ApiException('Pozycja '.$sort.' jest już zarezerwowana dla innego skryptu.');
		}
		
		if(is_null($sort)) {
			$sort = (is_array($t)?count($t):0)+100;
		}
		
		if($type=='file') {
			if(!isset($temp[$script])){
				$t[$sort] = array('file' => $script, 'code' => '');
				$temp[$script] = 1;
			}
		} else {
			$label = md5($script);
			if(!isset($temp[$label])){
				$t[$sort] = array('code' => $script, 'file' => '');
				$temp[$label] = 1;
			}
		}
		
		Registry::Remove($name);
		Registry::Set($name, $t);
		
		Registry::Remove($name.'_temp');
		Registry::Set($name.'_temp', $temp);
	}
	
	
	public final function AddSpryScript($script, $position='top') {

		if($position == 'top') {
			$name = 'javascript';
		} else {
			$name = 'footerJavascript';
		}

		$t = Registry::Get($name);
		
		$t[] = array('file' =>'Spry/' . $script, 'code' => '');
		Registry::Remove($name);
		Registry::Set($name, $t);
	}	
	/**
	 * Dodaje skrypt statystyk dla wp
	 *
	 * @param string $script
	 * @param string $type (file/code)
	 * @param string $position (top/bottom)
	 * @param int    $sort
	 */

	 public final function AddWpStatistics($key)
	 {
		$this->AddScript("var pp_gemius_identifier ='$key';
						  var pp_gemius_hitcollector = 'wp.hit.gemius.pl';",'code','top',0);
		$this->AddScript("WP.stat.dot('turystyka','','');", 'code', 'top', 2);

	 }
	/**
	 * Dodaje skrypt przed </body>
	 *
	 * @param string $script
	 * @param string $type
	 */
	public final function AddFooterScript($script, $type='file') {
		throw new ApiException('Metoda nieobslugiwana od wersji 1.1 Controllera. Uzyj AddScript z opcja bottom.');
	}

	/**
	 * Dodaje przekierowanie
	 *
	 * @param string $url
	 * @param int $time
	 */
	public final function AddRedirect($url, $time, $code=302) {
		
		if(is_array($url)) {
			Core::RequireOnce('plugins/Smarty/function.url.php');
			$urlData = smarty_function_url($url, $this->smarty);
		} else {
			$urlData = $url;
		}
		if($this->redirect['url']=='') {
			$this->redirect['url']=$urlData;
			$this->redirect['time']=$time;
			$this->redirect['code']=$code;
		}
	}

	/**
	 * Usuwa przekierowanie
	 *
	 */
	public final function ClearRedirect() {
		$this->redirect = array('url'=>'', 'time'=>'');
	}

	/**
	 * Sprawdza czy ustawione jest przekierowanie
	 *
	 * @return bool
	 */
	public final function IsRedirect() {
		if($this->redirect['url']!='') {
			$return = true;
		} else {
			$return = false;
		}

		return $return;
	}

	/**
	 * Zwraca url do przekierowania
	 *
	 * @return string
	 */
	public final function GetRedirect() {
		return $this->redirect;
	}

	/**
	 * Wylacza wyswietlenie szablonow
	 *
	 */
	public final function SetNoRender($headers = true) {
		
		if($headers)$this->SetAllMetaHeaders();
		
		$this->disableTemplates = true;
	}

	/**
	 * Uruchamianie obiektu klasy SharedController i wywolywanie pozadanej metody
	 *
	 * @param string $method
	 */
	public final function RunShared($method, $param=array()) {
		
		$this->smarty->assign('param', $param);
		$shared = new SharedController();

		$shared->SetSmarty($this->smarty);
		$shared->templatePath = 'partial/Shared/';
		$shared->partialTemplate = $method.'.tpl';
		

		$cacheParam = Utils::MultiImplode('-', $param, '-').$shared->partialTemplate;
		
		

		$shared->$method($param);

		
		$variable = strtolower(substr($method, 0, 1)) . substr($method, 1);
		
		$this->smarty->assign($variable, $this->smarty->fetch($shared->templatePath.$shared->partialTemplate, md5($cacheParam)));
	}

	/**
	 *
	 * Uruchamianie metody zewnetrzenego modulu
	 *
	 * @param string $module
	 * @param string $method
	 * @param string $param = null
	 * @param string $template = false - czy ma byc zaladowany template
	 *
	 */

	public final function RunModule($module,$method,$param = null,$template = false) {

		if(isset($param) && is_array($param)) {
			$cparam = Utils::MultiImplode('-', $param, '|');
		} else {
			$cparam = null;
		}

		$cacheParam = $module.$method.$template.$cparam;

		$param['cacheParam'] = $cacheParam;
		$moduleControllerName = $module;
		$moduleControllerName .= "Controller";

		require_once "controller/$moduleControllerName.php";

		$moduleController = new $moduleControllerName();

		if($template == true) {
			$moduleController->SetSmarty($this->smarty);
			$moduleController->templatePath = "partial/$module/";

			$moduleController->partialTemplate = $method.'.tpl';







			if(!$this->smarty->CacheControl($moduleController->templatePath.$moduleController->partialTemplate, array('cache_id'=> md5($cacheParam), 'lifetime'=>CacheParam::Get($module.$method)))) {
				if(!Core::GetAppSafeMode()) {
					$this->smarty->cache_lifetime = '0';
					$this->smarty->CacheControl($moduleController->templatePath.$moduleController->partialTemplate, array('cache_id'=> md5($cacheParam), 'write'=>true));
					return $moduleController->$method($param);
				}
			}



		}
		else {
			$moduleController->SetNoRender(false);
			return $moduleController->$method($param);
		}
	}


	public final function SetRequest(Request $request) {
		$this->request = $request;
	}

	/**
	 * Zwraca obiekt Request
	 *
	 * @return Request
	 */
	public final function Request() {
		return $this->request;
	}

	/**
	 * Zmienia szablon glowny na pusty dla akcji ajaxowych
	 *
	 */
	public final function SetAjaxRender() {
		$this->SetAllMetaHeaders();
		$this->renderer = 'ajax';
		
		$template = 'clean.tpl';
		Registry::Remove('smartyTemplate');
		Registry::Set('smartyTemplate', $template);
		Profiler::$profiling = false;
	}
	
	/**
	 * Zmienia szablon glowny na pusty dla akcji ajaxowych
	 *
	 */
	public final function SetValidatorRender() {
		$this->SetAllMetaHeaders();
		$this->renderer = 'validator';

		header("Content-type: text/javascript");
		
		$template = 'validator.tpl';
		Registry::Remove('smartyTemplate');
		Registry::Set('smartyTemplate', $template);
		Profiler::$profiling = false;
	}
	
	/**
	 * Zmienia szablon glowny na popoverowy
	 *
	 */
	public final function SetPopoverRender() {
		$this->renderer = 'popover';
		
		$this->SetAllMetaHeaders();
		$this->addStyle(URL_STATIC_CONTENT.'/css/Strona/popover_style.css',true);
		
		$template = 'popover.tpl';
		Registry::Remove('smartyTemplate');
		Registry::Set('smartyTemplate', $template);
		Profiler::$profiling = false;
	}

	public final function SetRender($type) {
		switch($type) {
			case 'ajax':
				$this->setAjaxRender();
				break;
			case 'popover':
				$this->setPopoverRender();
				break;
			case 'validator':
				$this->setValidatorRender();
				break;
			case 'no':
				$this->setNoRender();
				break;
			default:
		}
	
	}
	
	/**
	 * Ustawia sciezke powrotna
	 *
	 * @param array $path
	 */
	public final function SetReturnPath($path) {
		Registry::Set('smartyReturnPath', $path);
	}

	/**
	 * Dodaje element sciezki powrotnej
	 *
	 * array(title=>title, url=>url)
	 *
	 * @param array $item
	 */
	public final function AddReturnPathItem($item) {

		if(Registry::Exists('smartyReturnPath')) {
			$data = Registry::Get('smartyReturnPath');
			Registry::Remove('smartyReturnPath');
			$data[]=$item;
			Registry::Set('smartyReturnPath', $data);
		}
	}

	/**
	 * Zwaraca sciezke powrotna
	 *
	 * @return array
	 */
	public final function GetReturnPath() {
		return Registry::Get('smartyReturnPath');
	}

	/**
	 * Zwraca sformatowany url
	 *
	 * @param string $controller
	 * @param string $action
	 * @return string
	 */
	public final function GetMyUrl($controller,$action) {
		return str_replace('Action', '', $action).PATH_SEPARATOR.str_replace('Controller', '', $controller).APPLICATION_FILE_TYPE;
	}


	/**
	 * Sprawdza czy dana metoda ma byc zawsze uruchamiana (cache independent)
	 *
	 * @param string $method
	 * @return bool
	 */
	public final function CheckLiveMethod($method, $param = null) {
		if(isset($this->$method) || strstr('ajax', strtolower($method)) || (isset($param['liveMethod']) && $param['liveMethod']==true)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Zwraca oryginalne parametry z urla
	 *
	 * @param array $param
	 * @return array
	 */
	public final function GetUrlParam($param) {
		if(is_array($param) && isset($param['urlParam'])) {
			return array_reverse(explode(",", $param['urlParam']));
		} else {
			return array();
		}
	}



	public function SetActionSet($set) {

		$this->actionSet = $set;
	}

	public function LoadAdditionalModule($module, $controller) {
		if(is_file('controller/'.$module.'/'.str_replace($module.'_', '', ucfirst($controller)).'.php')) {
			Core::RequireOnce('controller/'.$module.'/'.str_replace($module.'_', '', ucfirst($controller)).'.php');
			MFLog::Debug('Loading module: '.$module.': '.$controller);
		} else {

			MFLog::Debug('Unable to load module, Loading controller: '.$controller);
			throw new CoreException('Unable to load module, Loading controller: '.$controller);
		}
	}

	public function LoadAdditionalController($controller) {

		if(is_file('controller/'.ucfirst($controller).'.php')) {
			Core::RequireOnce('controller/'.ucfirst($controller).'.php');
			MFLog::Debug('Loading module: '.$controller);
		} else {

			MFLog::Debug('Unable to load module, Loading controller: '.$controller);
			throw new CoreException('Unable to load module, Loading controller: '.$controller);
		}
	}

	public function RunAdditionalModule($controller, $method) {

		$controllerObj = null;

		if(class_exists($controller) && class_parents($controller) == Array('MainController'=>'MainController', 'Controller'=>'Controller') && class_implements($controller) == Array('ControllerInterface'=>'ControllerInterface')) {
			$controllerObj = new $controller();

			if(!method_exists($controllerObj, $method) && !method_exists($controllerObj, $method.'Action')) {
				MFLog::Debug('Method thoes not exists: '.$method);
				throw new CoreException('Method thoes not exists: '.$method);
			}
		} else {
			throw new CoreException('Brak klasy lub brak dziedziczenia!');
		}

		return $controllerObj;
	}

	public function DispatchAdditionalModule($controllerObj, $controller, $method, $module, $param, $liveMethod) {
		$controllerObj->SetSmarty($this->smarty);
		$controllerObj->partialTemplate = $method.'.tpl';

		$controllerObj->templatePath = 'partial/'.str_replace('_', '/', str_replace('Controller', '', $controller)).'/';


		if((!$controllerObj->Init($method, md5(implode($param, '-'))) || $controllerObj->CheckLiveMethod($method, $param) || $liveMethod) && $controllerObj->GetActionRedirect()!=true) {

			$methodAction = $method;
			$controllerObj->$methodAction($param);

		}


		if(!isset($controllerObj->content) && !$liveMethod) {
			//$this->smarty->cache_lifetime = $controllerObj->cacheTime;

			if(!$this->smarty->CacheControl($controllerObj->templatePath.$controllerObj->partialTemplate, array('cache_id'=> $method.substr(md5(implode($param, '-')),0,100), 'lifetime'=>$controllerObj->cacheTime)) && !Core::GetAppSafeMode()) {

				$this->smarty->CacheControl($controllerObj->templatePath.$controllerObj->partialTemplate, array('cache_id'=> $method.substr(md5(implode($param, '-')),0,100), 'write'=>true));
			}


			$controllerObj->content
			= $this->smarty->fetch($controllerObj->templatePath.$controllerObj->partialTemplate, $method.substr(md5(implode($param, '-')),0,100));


		}


		$this->smarty->append('zoneContent', $controllerObj->content);
	}

	public function GetActionSet() {
		return $this->actionSet;
	}

	public function ExecuteAdditionalActions($param) {
		$actionSetArray = $this->GetActionSet();
		$this->smarty->assign('zoneContent', '');

		foreach($actionSetArray as $actionSet) {
			if(isset($actionSet['liveMethod'])) {
				$liveMethod = true;
			} else {
				$liveMethod = false;

			}

			$this->LoadAdditionalController($actionSet['controller']);

			$controllerObj = $this->RunAdditionalModule($actionSet['controller'], $actionSet['method']);
			$this->DispatchAdditionalModule($controllerObj, $actionSet['controller'], $actionSet['method'], $actionSet['module'], $param, $liveMethod);
		}

	}

	private function SetAllMetaHeaders() {
		$true = 2;
		!Registry::Exists(self::DESCRIPTION_SET)?Registry::Set(self::DESCRIPTION_SET,$true):null;
		!Registry::Exists(self::TITLE_SET)?Registry::Set(self::TITLE_SET,$true):null;
		!Registry::Exists(self::KEYWORDS_SET)?Registry::Set(self::KEYWORDS_SET,$true):null;
	}
	
	
	//FUNKCJE DODANE TYLKO DLATEGO, �EBY BY�A DO NICH JAKA� DOKUMENTACJA

	/**
	 * Metoda wywolywana zawsze przed metoda akcji glownej @see IndexAction
	 *
	 * @param <array> $param
	 */
	public function IndexInit($param) {
	}

	/**
	 * Metoda wywolywana gdy akcja glowna jest wczytywana z cache'a i nie wywolywana jest metoda @see IndexAction (WTEDY I TYLKO WTEDY)
	 * @param <array> $param
	 */
	public function IndexCached($param) {
	}


	public function preDispatch($param) {

	}

	public function postDispatch($param) {
		
	}
}

?>